#ifndef _TDA_SYNTH_H_

#define _TDA_SYNTH_H_

#include "common.h"

#define MAX_FUNCTION_NAME	14
#define MAX_ARGS		3
#define MAX_MOD_STEPS		3

#define MOD_STEP_ATTACK_MIN	function_linear
#define MOD_STEP_ATTACK_MAX	function_tri
#define MOD_STEP_SUSTAIN_MIN	function_constant
#define MOD_STEP_SUSTAIN_MAX	function_invlog
#define MOD_STEP_DECAY_MIN	function_invlinear
#define MOD_STEP_DECAY_MAX	function_invlog

typedef struct{
	float args[MAX_ARGS];
	float (* function_mod)(float,float,float,float);
} function_struct_t;

typedef struct{
	float intensity;
	float multiplier;
} harmonic_struct_t;

typedef struct{

	int harmonics_qty;
	harmonic_struct_t * harmonics;
	
	function_struct_t mod_steps[MAX_MOD_STEPS];
	
} adt_synth_t;

typedef enum {function_linear=0, function_exp=1, function_quartsin=2, function_halfsin=3, function_log=4, function_tri=5, function_constant=6, function_sin=7, function_pulses=8, function_invlinear=9, function_invexp=10, function_quartcos=11, function_halfcos=12, function_invlog=13} function_mod_t;
typedef enum {ATTACK, SUSTAIN, DECAY} mod_step_t;

status_t adt_synth_new (adt_synth_t ** pp_adt_synth, FILE * synth_data);
status_t adt_synth_load_data (adt_synth_t * p_adt_synth, FILE * fi);
status_t adt_synth_destroy(adt_synth_t ** pp_adt_synth);

status_t adt_synth_set_harmonics_qty(adt_synth_t * p_adt_synth,int qty);
status_t adt_synth_set_harmonic_multiplier(adt_synth_t * p_adt_synth,float multiplier,size_t n_harmonic);
status_t adt_synth_set_harmonic_intensity(adt_synth_t * p_adt_synth,float intensity,size_t n_harmonic);
status_t adt_synth_set_function(adt_synth_t * p_adt_synth, float (*function)(float,float,float,float),mod_step_t mod_step);
status_t adt_synth_set_function_arg(adt_synth_t * p_adt_synth,float arg,mod_step_t mod_step,size_t n_arg);

int adt_synth_get_harmonics_qty(adt_synth_t * p_adt_synth);
float adt_synth_get_harmonic_multiplier(adt_synth_t * p_adt_synth,size_t n_harmonic);
float adt_synth_get_harmonic_intensity(adt_synth_t * p_adt_synth,size_t n_harmonic);
float(* adt_synth_get_function(adt_synth_t * p_adt_synth,mod_step_t mod_step))(float,float,float,float);
float adt_synth_get_function_arg(adt_synth_t * p_adt_synth,mod_step_t mod_step,size_t n_arg);

status_t convert_string_to_function_mod_t(char * s, function_mod_t * function);
#endif

